package com.h3bpm.web.service.impl;

import OThinker.Common.Data.BoolMatchValue;
import OThinker.Common.Data.Database.Parameter;
import OThinker.Common.Data.DbType;
import OThinker.Common.Organization.Models.OrganizationUnit;
import OThinker.Common.Organization.Models.Unit;
import OThinker.Common.Organization.Models.User;
import OThinker.H3.Controller.RestfulApi.cloudpivot.ResponseResult;
import OThinker.H3.Entity.Data.Attachment.Attachment;
import OThinker.H3.Entity.Data.Attachment.AttachmentHeader;
import OThinker.H3.Entity.DataModel.BizObject;
import OThinker.H3.Entity.Instance.Data.InstanceData;
import OThinker.H3.Entity.Instance.Token;
import OThinker.H3.Entity.Tracking.UserLog;
import OThinker.H3.Entity.Tracking.UserLogType;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.h3bpm.base.engine.client.EngineClient;
import com.h3bpm.base.util.AppUtility;
import com.h3bpm.base.util.SheetUtility;
import com.h3bpm.web.qjcEnum.ContractStatusEnum;
import com.h3bpm.web.service.ContractService;
import com.h3bpm.web.utils.*;
import com.h3bpm.web.utils.DocxUnitl;
import com.h3bpm.web.utils.MatrixToImageWriter;
import com.h3bpm.web.utils.QjcUtils;
import data.DataException;
import data.DataRow;
import data.DataRowCollection;
import data.DataTable;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static OThinker.H3.Controller.ControllerBase.getEngine;
import static com.h3bpm.web.utils.DateUtils.getQuarter;
import static com.h3bpm.web.utils.DateUtils.timeCompare;

@Service
public class ContractServiceImpl implements ContractService, CommandLineRunner {
    private static final Logger logger = LoggerFactory.getLogger(ContractServiceImpl.class);


    private EngineClient engineClient = null;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Value("${webHost:http://127.0.0.1}")
    private String webHost;



    @Override
    public void run(String... args) {

        engineClient = (EngineClient) AppUtility.getEngine();
    }


    /**
     * 生成合同编码, 原先 手动生成编号 由相对方给的合同编号 用其他字段记录,现在合同编号都需要自动生成
     *
     * @param instanceId 实例id
     * @param userId     用户id
     * @return ResponseResult
     */
    @Override
    public ResponseResult contractCodeGenerate(String instanceId, String userId) {
        ResponseResult rst = new ResponseResult(-1L, "", null);
        try {


            InstanceData instanceData = new InstanceData(engineClient, instanceId, userId);
            BizObject bizObject = instanceData.getBizObject();

            String contractNum = (String) bizObject.GetValue("contractNum");

            if (StringUtils.isNoneBlank(contractNum)) {
                rst.setErrmsg(contractNum);
                rst.setErrcode(0L);
                return rst;
            }


            String parentContractNumber = (String) bizObject.GetValue("parentContractNumber");
            if (StringUtils.isNotEmpty(parentContractNumber)) {
                rst.setErrmsg(parentContractNumber.concat("G"));
                rst.setErrcode(0L);
            } else {

                String contractCode = getContractCode(instanceData);

                if (contractCode != null) {
                    logger.info("流程 instId = {},通过编码规则,获取合同编码成功,code ={}",instanceData.getInstanceId(),contractCode);

                    rst.setErrmsg(contractCode);
                    rst.setErrcode(0L);

                } else {
                    rst.setErrmsg("自动生成合同编号失败...");
                    return rst;
                }

            }
            instanceData.getBizObject().SetValue("contractNum", rst.getErrmsg());
            instanceData.Submit();

        } catch (Exception e) {
            logger.info("获取合同编码失败:"+e.getMessage(),e);
            rst.setErrmsg("获取合同编号系统异常...");
        }

        return rst;
    }

    /**
     *  自动生成合同,目前有两种类型
     *  1. 年份+合同性质（S/Z)+部门+合同类型+流水号（XXX) ====  {YYYY}-{SZ}-{DEPT}-{TYPE}-{XXX}
     *  2. 有服务市场的合同编码 年份+合同性质（S/Z)+部门+合同类型+服务市场业务编码+产品识别+流水号（XXX)
     *      {YYYY}-{SZ}-{DEPT}-{TYPE}-{FWSC}-{SB}-{XXX}
     */
    private String getContractCode(InstanceData instData ) throws Exception {
        String generationRole1 = "{YYYY}-{SZ}-{DEPT}-{TYPE}-{XXXX}";
        String generationRole2 = "{YYYY}-{SZ}-{DEPT}-{TYPE}-{FWSC}-{SB}-{XXXX}";
        String generationRole = generationRole1;
        // 年月日
        String yyyy = DateFormatUtils.format(new Date(), "yyyy"),
                // 合同性质编码
                nature = "",
                // 合同部门编码
                deptCode = "",
                // 合同类型编码
                contractType = "";

        //合同部门编码
        deptCode = (String) instData.getBizObject().GetValue("deptCode");

        // 合同性质编码 赋值
        String expensesOrReceipts = (String) instData.getBizObject().GetValue("expensesOrReceipts");
        if ("收入".equals(expensesOrReceipts)){
            nature = "S";
        }else {
            nature = "Z";
        }

        // 合同类型编码
        contractType = (String) instData.getBizObject().GetValue("contractTypeCode");

        //合同服务市场类型
        String serviceMarketCode = (String) instData.getBizObject().GetValue("serviceMarketCode");
        //服务市场业务编码
        String serviceContractTypeCode = "",
                //产品识别编码
                productIdentityCode = "",
                stc = "";
        if (StringUtils.isNotBlank(serviceMarketCode)) {
            generationRole = generationRole2;
            serviceContractTypeCode = (String) instData.getBizObject().GetValue("serviceContractTypeCode");
            productIdentityCode = (String) instData.getBizObject().GetValue("productIdentityCode");
            if(StringUtils.isNotBlank(serviceContractTypeCode)){
                stc = serviceMarketCode.concat("-").concat(serviceContractTypeCode);
            }else{
                stc = serviceMarketCode;
            }
        }


        String code = generationRole.replace("{YYYY}",yyyy).replace("{SZ}",nature)
                .replace("{DEPT}",deptCode).replace("{TYPE}",contractType)
                .replace("{FWSC}",stc) .replace("{SB}",productIdentityCode).replace("--","-") ;
        // 按 codeFlag 查询合同 编号
        code = getContractNumber(code, instData.getInstanceId());

        return code;

    }

    /**
     *  获取合同编码 排序
     * @param code
     * @return
     */
    private String getContractNumber (String code,String instId) throws Exception {

        String  sql = "select count(1) as count from contract_number_class where code = '%s'";

        int count = engineClient.getPortalQuery().count(String.format(sql, code));

        int classId = 0;

        if (count == 0){
            sql = "insert into contract_number_class (code)values('%s')";

            engineClient.getPortalQuery().ExcuteNoQuery(String.format(sql, code));
        }
        //查询 classId
        sql = "select id from contract_number_class where code = '%s' limit 1";

        DataTable dataTable = engineClient.getPortalQuery().QueryTable(String.format(sql, code));

        classId = dataTable.getRows().get(0).getInt("id");

        //查询 合同编码总数
        sql = "select count(1) from contract_number_pool where classId = '%s' ";

        count = engineClient.getPortalQuery().count(String.format(sql, classId));

        // 生成编号并保存
        count++;

        String number = String.valueOf(count);

        String str = code.substring(code.lastIndexOf("{")+1, code.lastIndexOf("}") );

        int padlen = number.length();

        if(padlen < str.length()){
            padlen = str.length();
        }
        //合同编号 左边 0 补齐
        number =  StringUtils.leftPad(number, padlen, "0");

        code = code.replaceAll("\\{X+\\}", number);

        sql = "insert into contract_number_pool (code,instanceId,classId,number) values('%s','%s','%s','%s')";

        sql = String.format(sql, code, instId, classId, count);
        // 插入合同编号池
        int i = engineClient.getPortalQuery().ExcuteNoQuery(sql);

        if (i > 0) {
            return  code;
        }

        return  null;

    }




    @Override
    public int insetContractMasterData(InstanceData instanceData) {
        int rst;
        String tbName = "i_contractData";
        try {
            BizObject bizObject = instanceData.getBizObject();
            String contractNum = (String) bizObject.GetValue("contractNum");
            Parameter[] param = new Parameter[]{new Parameter("contractNum", DbType.String, contractNum)};
            rst = dataCount(tbName, param);

            if (rst > 0) {
                logger.info("主数据已存在,无需写入,instaceId ={}", instanceData.getInstanceId());
                return 1;
            }

            List<Parameter> paramList = new ArrayList<>();

            //ObjectID
            paramList.add(new Parameter("ObjectID", DbType.String, UUID.randomUUID()));
            //Name
            paramList.add(new Parameter("Name", DbType.String, bizObject.GetValue("contractName")));
            //CreatedBy
            paramList.add(new Parameter("CreatedBy", DbType.String, bizObject.GetValue("CreatedBy")));
            //CreatedTime
            paramList.add(new Parameter("CreatedTime", DbType.DateTime, bizObject.GetValue("CreatedTime")));
            //instId
            paramList.add(new Parameter("instId", DbType.String, instanceData.getInstanceId()));

            //签约单位
            paramList.add(new Parameter("firstPartyName", DbType.String, bizObject.GetValue("firstPartyName")));
            //合同名称
            paramList.add(new Parameter("contractName", DbType.String, bizObject.GetValue("contractName")));
            //合同编号
            paramList.add(new Parameter("contractNum", DbType.String, contractNum));
            //签约日期
            paramList.add(new Parameter("signDate", DbType.DateTime, bizObject.GetValue("signDate")));
            //收入/支出
            paramList.add(new Parameter("expensesOrReceipts", DbType.String, bizObject.GetValue("expensesOrReceipts")));
            //合同金额
            paramList.add(new Parameter("totalMoney", DbType.String, bizObject.GetValue("totalMoney")));
            //合同标的物
            paramList.add(new Parameter("goodsName", DbType.String, bizObject.GetValue("goodsName")));
            //甲方签约人
            paramList.add(new Parameter("firstSignatory", DbType.String, bizObject.GetValue("signatory")));

            //签约对方单位名称
            paramList.add(new Parameter("secondPartyName", DbType.String, bizObject.GetValue("secondPartyName")));

            //乙方签约人
            paramList.add(new Parameter("secondSignatory", DbType.String, bizObject.GetValue("secondSignatory")));

            //合同开始时间
            paramList.add(new Parameter("startDate", DbType.DateTime, bizObject.GetValue("startDate")));
            //合同结束时间
            Date endDate = (Date) bizObject.GetValue("endDate");
            paramList.add(new Parameter("endDate", DbType.DateTime, endDate));
            //实际结束时间
//            paramList.add(new Parameter("performanceTime", DbType.DateTime, bizObject.GetValue(null)));
            //是否超期
            paramList.add(new Parameter("Overdue", DbType.String, "否"));
            //有无变更
            paramList.add(new Parameter("beContractChanges", DbType.String, "无"));
            //备注
            paramList.add(new Parameter("remarks", DbType.String, bizObject.GetValue("remarks")));
//            //合同种类
//            paramList.add(new Parameter("contractClass", DbType.String, bizObject.GetValue("contractClass")));
            // 信用期限
            String deadlineForPerformance = (String) bizObject.GetValue("deadlineForPerformance");
            int num = StringUtils.isNoneBlank(deadlineForPerformance) ? Integer.parseInt(deadlineForPerformance) : 0;
            paramList.add(new Parameter("creditPeriod", DbType.String, num));
            //合同状态
            paramList.add(new Parameter("contractStatus", DbType.String, ContractStatusEnum.htqsz.getValue()));
            // 合同信用结束时间
            Date deadlineForCreditDate = DateUtils.addMonths(endDate, num);
            paramList.add(new Parameter("creditDateDeadline", DbType.DateTime, deadlineForCreditDate));
            //合同年度
            paramList.add(new Parameter("contractYear", DbType.String, DateFormatUtils.format(endDate, "yyyy")));

            paramList.add(new Parameter("serviceMarket", DbType.String, bizObject.GetValue("serviceMarket")));
            //合同季度
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(endDate);
            String quarter = getQuarter(calendar.get(Calendar.MONTH) + 1);
            paramList.add(new Parameter("quarter", DbType.String, quarter));

            //甲方企业信用代码
            paramList.add(new Parameter("firstBusinesRegistNumber", DbType.String, bizObject.GetValue("businesRegistNumber")));
            //乙方企业信用代码
            paramList.add(new Parameter("secondBusinesRegistNumber", DbType.String, bizObject.GetValue("secondBusinesRegistNumber")));
            //企业信用代码
            paramList.add(new Parameter("archive", DbType.String, "未归档"));
            paramList.add(new Parameter("workflowStatus", DbType.String, "流程结束"));
            //合同类型
            paramList.add(new Parameter("contractType", DbType.String, bizObject.GetValue("contractType")));
            //经办人
            paramList.add(new Parameter("contractOperator", DbType.String, instanceData.getInstanceContext().getOriginatorName()));

            paramList.add(new Parameter("secondAgent", DbType.String, bizObject.GetValue("secondAgent")));

            paramList.add(new Parameter("firstAgent", DbType.String, bizObject.GetValue("firstAgent")));

            paramList.add(new Parameter("originalContractNum", DbType.String, contractNum));

            String orgUserId =  instanceData.getInstanceContext().getOriginator();
            Unit unit = getEngine().getOrganization().GetParentUnitByCategoryCode(orgUserId,"dept");

            if (unit == null) {
                unit = getEngine().getOrganization().GetUnit(instanceData.getInstanceContext().getOrgUnit());

            }
            //发起部门
            paramList.add(new Parameter("createdByDepartment", DbType.String, unit.getName()));
            paramList.add(new Parameter("CreatedByParentId", DbType.String, unit.getObjectID()));
            //发起部门ID
            paramList.add(new Parameter("createdByDepartmentId", DbType.String, unit.getObjectID()));
            //对方名称
            paramList.add(new Parameter("oppositeUnit", DbType.String, bizObject.GetValue("oppositeUnit")));
            paramList.add(new Parameter("CRRCAgent", DbType.String, bizObject.GetValue("CRRCAgent")));
            paramList.add(new Parameter("CRRCSignatory", DbType.String, bizObject.GetValue("CRRCSignatory")));


            String[] value = new String[paramList.size()];
            String[] col = new String[paramList.size()];

            for (int i = 0; i < value.length; i++) {
                value[i] = "?";
                col[i] = paramList.get(i).getName();
            }
            String sql = String.format("insert into i_contractData ( %s) value ( %s ) ", StringUtils.join(col, ","), StringUtils.join(value, ","));

            if (logger.isDebugEnabled()) {
                logger.info("写入主数据 sql = {}", sql);
            }

            rst = engineClient.getPortalQuery().ExcuteNoQuery(sql, paramList.toArray(new Parameter[0]));
        } catch (Exception e) {
            e.printStackTrace();
            rst = 0;
        }


        return rst;

    }

    @Override
    public int insetSealRegistrationData(InstanceData instanceData) {
        int rst;
        String tbName = "i_sealRegistration";
        try {

            BizObject bizObject = instanceData.getBizObject();
            String contractNum = (String) bizObject.GetValue("contractNum");
            Parameter[] param = new Parameter[]{new Parameter("contractNumber", DbType.String, contractNum)};
            rst = dataCount(tbName, param);

            if (rst > 0) {
                logger.info("用印数据已存在,无需写入 {}", instanceData.getInstanceId());
                return 1;
            }

            List<Parameter> paramList = new ArrayList<>();
            String serviceMarket = (String) bizObject.GetValue("serviceMarket");

            //ObjectID
            paramList.add(new Parameter("ObjectID", DbType.String, UUID.randomUUID()));
            //Name
            paramList.add(new Parameter("Name", DbType.String, bizObject.GetValue("contractName")));
            //CreatedBy
            paramList.add(new Parameter("CreatedBy", DbType.String, bizObject.GetValue("CreatedBy")));
            //CreatedTime
            paramList.add(new Parameter("CreatedTime", DbType.DateTime, bizObject.GetValue("CreatedTime")));
            //合同订立流程id
            paramList.add(new Parameter("instId", DbType.String, instanceData.getInstanceId()));

            //用章编号
            paramList.add(new Parameter("seal", DbType.String, bizObject.GetValue("sealType")));
            //服务市场 [serviceMarket]
            paramList.add(new Parameter("serviceMarket", DbType.String, serviceMarket));
            //合同名称 [contractName]
            paramList.add(new Parameter("contractName", DbType.String, bizObject.GetValue("contractName")));
            //合同编号 [contractNumber]
            paramList.add(new Parameter("contractNumber", DbType.String, contractNum));
            //合同总金额 [totalMoney]
            paramList.add(new Parameter("totalMoney", DbType.String, bizObject.GetValue("totalMoney")));
            paramList.add(new Parameter("oppositeUnit", DbType.String, bizObject.GetValue("oppositeUnit")));
            paramList.add(new Parameter("CRRCAgent", DbType.String, bizObject.GetValue("CRRCAgent")));
            paramList.add(new Parameter("CRRCSignatory", DbType.String, bizObject.GetValue("CRRCSignatory")));
            //盖章日期 [stampedDate]
            paramList.add(new Parameter("stampedDate", DbType.DateTime, bizObject.GetValue("stampedDate")));
            //备注 [remarks]
            paramList.add(new Parameter("remarks", DbType.String, bizObject.GetValue("remarks")));

            String orgUserId =  instanceData.getInstanceContext().getOriginator();
            Unit unit = getEngine().getOrganization().GetParentUnitByCategoryCode(orgUserId,"dept");

            if (unit == null) {
                unit = getEngine().getOrganization().GetUnit(instanceData.getInstanceContext().getOrgUnit());

            }
            paramList.add(new Parameter("createdByDepartment", DbType.String, unit.getName()));
            paramList.add(new Parameter("CreatedByParentId", DbType.String, unit.getObjectID()));
            List<Token> tokens = instanceData.getInstanceContext().getTokens();
            List<Token> collect = tokens.stream().filter(ac -> "Activity47".equals(ac.getActivity())).collect(Collectors.toList());

            //日期 [approvalTime]
            paramList.add(new Parameter("approvalTime", DbType.DateTime, collect.get(0).getCreatedTime()));

            StringBuilder col = new StringBuilder();
            StringBuilder value = new StringBuilder();

            for (Parameter parameter : paramList) {
                col.append(parameter.getName()).append(",");
                value.append("?, ");
            }

            String sql = String.format("insert into %s ( %s) value ( %s ) ", tbName, col.substring(0, col.lastIndexOf(",")),
                    value.substring(0, value.lastIndexOf(",")));

            if (logger.isDebugEnabled()) {
                logger.info("用印台账写入主数据 sql = {}", sql);
            }


            rst = engineClient.getPortalQuery().ExcuteNoQuery(sql, paramList.toArray(new Parameter[0]));
        } catch (Exception e) {
            e.printStackTrace();
            rst = 0;
        }


        return rst;
    }

    /**
     * 查询数据行数
     *
     * @param tbName     表名
     * @param parameters 字段及参数
     * @return int
     */
    public int dataCount(String tbName, Parameter[] parameters) {

        String sql = String.format("select count(1) as count from %s ", tbName);

        if (parameters != null) {
            StringBuilder param = new StringBuilder();

            for (Parameter parameter : parameters) {
                param.append(parameter.getName()).append(" = ? ").append(" and ");
            }

            if (param.length() > 0) {
                sql = sql.concat(" where ").concat(param.substring(0, param.lastIndexOf("and")));
            }

        }

        return engineClient.getPortalQuery().count(sql, parameters);
    }

    @Override
    public Object getCountersignedStaff(String instanceId) {
        try {
            InstanceData instanceData = new InstanceData(engineClient, instanceId, User.AdministratorID);
            Object userData = instanceData.getBizObject().GetValue("countersignedStaff");
            return userData;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public boolean updateContractToArchive(String objectId) {
        String sql = "update i_contractdata set Archive = '已归档' WHERE ObjectID = ?";
        Parameter[] params = new Parameter[1];
        params[0] = new Parameter("objectId", DbType.String, objectId);
        int i = engineClient.getPortalQuery().ExcuteNoQuery(sql, params);
        if (i > 0) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean updateContractTemplateStatus(String instanceId, String status) {
        String sql = "update i_uploadcontracttemplate set contractTemplateStatus = ? WHERE instId = ?";
        String enableStatus = "启用";
        String disableStatus = "禁用";
        String templateStatus;
        if (enableStatus.equals(status)) {
            templateStatus = disableStatus;
        } else if (disableStatus.equals(status)) {
            templateStatus = enableStatus;
        } else {
            return false;
        }
        Parameter[] params = new Parameter[2];
        params[0] = new Parameter("templateStatus", DbType.String, templateStatus);
        params[1] = new Parameter("instanceId", DbType.String, instanceId);
        int i = engineClient.getPortalQuery().ExcuteNoQuery(sql, params);
        if (i > 0) {
            logger.info("合同模板状态修改成功");
            return true;
        }
        return false;
    }


    @Override
    public boolean updateWorkflowStatusToBegin(String objectId) {
        String sql = "update i_contractdata set workflowStatus = '流程开始' WHERE ObjectID = ?";
        Parameter[] params = new Parameter[1];
        params[0] = new Parameter("objectId", DbType.String, objectId);
        int i = engineClient.getPortalQuery().ExcuteNoQuery(sql, params);
        if (i > 0) {
            return true;
        }
        return false;
    }

    @Override
    public boolean updateWorkflowStatusToEnd(String objectId) {
        String sql = "update i_contractdata set workflowStatus = '流程结束' WHERE ObjectID = ?";
        Parameter[] params = new Parameter[1];
        params[0] = new Parameter("objectId", DbType.String, objectId);
        int i = engineClient.getPortalQuery().ExcuteNoQuery(sql, params);
        if (i > 0) {
            return true;
        }
        return false;
    }

    @Override
    public boolean updateContractStatusToExecuting(String instanceId) {
        String sql = "update i_contractdata set contractStatus = ? WHERE instId = ?";
        Parameter[] params = new Parameter[2];
        params[0] = new Parameter("contractStatus", DbType.String,ContractStatusEnum.zxz.getValue());
        params[1] = new Parameter("instId", DbType.String, instanceId);
        int i = engineClient.getPortalQuery().ExcuteNoQuery(sql, params);
        if (i > 0) {
            logger.info("合同主数据合同生命周期状态为执行中，执行成功 instId ={}",instanceId);
            return true;
        }
        return false;
    }



    @Override
    public boolean contractChangesCodeGenerate(String instanceId)throws Exception {
        String stringTemplate ="contractCount";
        String sql = "select count(1) as contractCount from i_contractdata where originalContractNum = ?";
        String contractChangesCode = null;
        InstanceData instanceData = null;
        instanceData = new InstanceData(engineClient, instanceId, User.AdministratorID);
        Object originalContractNumObj = instanceData.getBizObject().GetValue("originalContractNum");
        String originalContractNumber = String.valueOf(originalContractNumObj);
        Parameter[] params = new Parameter[1];
        params[0] = new Parameter("originalContractNum", DbType.String, originalContractNumber);
        DataTable dataTable = engineClient.getPortalQuery().QueryTable(sql, params);
        DataRowCollection queryRows = dataTable.getRows();
        if (queryRows != null && queryRows.size() > 0 && queryRows.get(0).getString(stringTemplate) != null&&!"".equals(queryRows.get(0).getString(stringTemplate)) ) {
            DataRow dataRow = queryRows.get(0);
            String contractCount = dataRow.getString("contractCount");
            logger.info("获取到已生成的合同变更编号数,num = {}", contractCount);
            int countNum = Integer.parseInt(contractCount);
            String suffixNum = "-" + countNum;
            contractChangesCode = originalContractNumber + suffixNum;
            instanceData.getBizObject().SetValue("contractNum", contractChangesCode);
            instanceData.Submit();
            return true;
        } else {
            logger.info("生成合同变更号，未取到该合同的原始合同号总数，请检查参数");
            return false;
        }
    }


    @Override
    public boolean contractRelieveCodeGenerate(String instanceId)throws Exception {
        InstanceData instanceData = null;
        instanceData = new InstanceData(engineClient, instanceId, User.AdministratorID);
        Object showContractNumObj = instanceData.getBizObject().GetValue("showContractNum");
        String suffixNum = "-jc";
        String contractRelieveCode = null;
        if (showContractNumObj!=null){
            String originalContractNum = String.valueOf(showContractNumObj);
            contractRelieveCode = originalContractNum + suffixNum;
            instanceData.getBizObject().SetValue("contractNum", contractRelieveCode);
            instanceData.Submit();
            logger.info("生成合同解除编号成功，instanceId： {}",instanceId);
            return true;
        } else {
            logger.info("生成合同解除编号，未取到该合同的原始合同号总数，请检查参数，instanceId： {}",instanceId);
            return false;
        }
    }


    @Override
    public boolean insertChangesContractData(InstanceData instanceData) throws Exception {
        int rst;
        String tbName = "i_contractdata";
        logger.info("开始写入合同主数据,instaceId ={}", instanceData.getInstanceId());
        BizObject bizObject = instanceData.getBizObject();
        String contractNum = (String) bizObject.GetValue("contractNum");
        Parameter[] param = new Parameter[]{new Parameter("contractNum", DbType.String, contractNum)};
        rst = dataCount(tbName, param);

        if (rst > 0) {
            logger.info("主数据已存在,无需写入,instaceId ={}", instanceData.getInstanceId());
            throw new Exception("该合同编号的数据已存在");
        }
        List<Parameter> paramList = new ArrayList<>();

        //ObjectID
        paramList.add(new Parameter("ObjectID", DbType.String, UUID.randomUUID()));
        //Name
        paramList.add(new Parameter("Name", DbType.String, bizObject.GetValue("contractName")));
        //CreatedBy
        paramList.add(new Parameter("CreatedBy", DbType.String, bizObject.GetValue("CreatedBy")));
        //CreatedTime
        paramList.add(new Parameter("CreatedTime", DbType.DateTime, bizObject.GetValue("CreatedTime")));
        //instId
        paramList.add(new Parameter("instId", DbType.String, instanceData.getInstanceId()));

        //签约单位
        paramList.add(new Parameter("firstPartyName", DbType.String, bizObject.GetValue("firstPartyName")));
        //合同名称
        paramList.add(new Parameter("contractName", DbType.String, bizObject.GetValue("contractName")));
        //合同编号
        paramList.add(new Parameter("contractNum", DbType.String, contractNum));
        //签约日期
        paramList.add(new Parameter("signDate", DbType.DateTime, bizObject.GetValue("signDate")));
        //收入/支出
        paramList.add(new Parameter("expensesOrReceipts", DbType.String, bizObject.GetValue("expensesOrReceipts")));
        //合同金额
        paramList.add(new Parameter("totalMoney", DbType.String, bizObject.GetValue("totalMoney")));
        //合同标的物
        paramList.add(new Parameter("goodsName", DbType.String, bizObject.GetValue("goodsName")));
        //甲方签约人
        paramList.add(new Parameter("firstSignatory", DbType.String, bizObject.GetValue("signatory")));

        //签约对方单位名称
        paramList.add(new Parameter("secondPartyName", DbType.String, bizObject.GetValue("secondPartyName")));

        //乙方签约人
        paramList.add(new Parameter("secondSignatory", DbType.String, bizObject.GetValue("secondSignatory")));

        //合同开始时间
        paramList.add(new Parameter("startDate", DbType.DateTime, bizObject.GetValue("startDate")));
        //合同结束时间
        Date endDate = (Date) bizObject.GetValue("endDate");
        paramList.add(new Parameter("endDate", DbType.DateTime, endDate));
        //实际结束时间
//            paramList.add(new Parameter("performanceTime", DbType.DateTime, bizObject.GetValue(null)));
        //是否超期
        paramList.add(new Parameter("Overdue", DbType.String, "否"));
        //有无变更
        paramList.add(new Parameter("beContractChanges", DbType.String, "无"));
        //备注
        paramList.add(new Parameter("remarks", DbType.String, bizObject.GetValue("remarks")));
//            //合同种类
//            paramList.add(new Parameter("contractClass", DbType.String, bizObject.GetValue("contractClass")));
        // 信用期限
        String deadlineForPerformance = (String) bizObject.GetValue("deadlineForPerformance");
        int num = StringUtils.isNoneBlank(deadlineForPerformance) ? Integer.parseInt(deadlineForPerformance) : 0;
        paramList.add(new Parameter("creditPeriod", DbType.String, num));
        //合同状态
        paramList.add(new Parameter("contractStatus", DbType.String, ContractStatusEnum.htqsz.getValue()));
        // 合同信用结束时间
        Date deadlineForCreditDate = DateUtils.addMonths(endDate, num);
        paramList.add(new Parameter("creditDateDeadline", DbType.DateTime, deadlineForCreditDate));
        //合同年度
        paramList.add(new Parameter("contractYear", DbType.String, DateFormatUtils.format(endDate, "yyyy")));

        //合同季度
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endDate);
        String quarter = getQuarter(calendar.get(Calendar.MONTH) + 1);
        paramList.add(new Parameter("quarter", DbType.String, quarter));

        //甲方企业信用代码
        paramList.add(new Parameter("firstBusinesRegistNumber", DbType.String, bizObject.GetValue("businesRegistNumber")));
        //乙方企业信用代码
        paramList.add(new Parameter("secondBusinesRegistNumber", DbType.String, bizObject.GetValue("secondBusinesRegistNumber")));
        //企业信用代码
        paramList.add(new Parameter("archive", DbType.String, "未归档"));
        paramList.add(new Parameter("workflowStatus", DbType.String, "流程结束"));
        //合同类型
        paramList.add(new Parameter("contractType", DbType.String, bizObject.GetValue("contractType")));
        //经办人
        paramList.add(new Parameter("contractOperator", DbType.String, instanceData.getInstanceContext().getOriginatorName()));

        paramList.add(new Parameter("secondAgent", DbType.String, bizObject.GetValue("secondAgent")));

        paramList.add(new Parameter("firstAgent", DbType.String, bizObject.GetValue("firstAgent")));

        paramList.add(new Parameter("serviceMarket", DbType.String, bizObject.GetValue("serviceMarket")));

        String orgUserId =  instanceData.getInstanceContext().getOriginator();
        Unit unit = getEngine().getOrganization().GetParentUnitByCategoryCode(orgUserId,"dept");

        if (unit == null) {
            unit = getEngine().getOrganization().GetUnit(instanceData.getInstanceContext().getOrgUnit());

        }
        //发起部门
        paramList.add(new Parameter("createdByDepartment", DbType.String, unit.getName()));

        paramList.add(new Parameter("CreatedByParentId", DbType.String, unit.getObjectID()));
        //发起部门ID
        paramList.add(new Parameter("createdByDepartmentId", DbType.String, unit.getObjectID()));
        //对方名称
        paramList.add(new Parameter("oppositeUnit", DbType.String, bizObject.GetValue("oppositeUnit")));
        paramList.add(new Parameter("CRRCAgent", DbType.String, bizObject.GetValue("CRRCAgent")));
        paramList.add(new Parameter("CRRCSignatory", DbType.String, bizObject.GetValue("CRRCSignatory")));
        String updateSql=null;
        Object totalMoney = bizObject.GetValue("totalMoney");
        Object masterObjectId = bizObject.GetValue("masterObjectId");
        Parameter[] params;
        Object alteration = bizObject.GetValue("alteration");
        // alteration（变更事项）不为空变更合同，为空为解除协议，涉及到变更后合同号和解除协议合同号
        if (alteration != null && !"".equals(alteration)) {
            updateSql="UPDATE  i_contractdata SET totalMoney = ?,beContractChanges='有' where ObjectID= ?";
            params= new Parameter[2];
            params[0] = new Parameter("totalMoney", DbType.Decimal, 0);
            params[1] = new Parameter("objectId", DbType.String, masterObjectId);
            paramList.add(new Parameter("originalContractNum", DbType.String, bizObject.GetValue("originalContractNum")));
            logger.info("插入变更合同数据  {}",contractNum);
        } else {
            updateSql="UPDATE  i_contractdata SET totalMoney = ? where ObjectID= ?";
            params = new Parameter[2];
            params[0] = new Parameter("totalMoney", DbType.Decimal, 0);
            params[1] = new Parameter("objectId", DbType.String, masterObjectId);
            paramList.add(new Parameter("originalContractNum", DbType.String, contractNum));
            paramList.add(new Parameter("actualPayment", DbType.String, bizObject.GetValue("actualPayment")));
            logger.info("插入解除协议合同数据  {}",contractNum);
        }

        String[] value = new String[paramList.size()];
        String[] col = new String[paramList.size()];

        for (int i = 0; i < value.length; i++) {
            value[i] = "?";
            col[i] = paramList.get(i).getName();
        }
        String sql = String.format("insert into i_contractData ( %s) value ( %s ) ", StringUtils.join(col, ","), StringUtils.join(value, ","));

        if (logger.isDebugEnabled()) {
            logger.info("写入主数据 sql = {}", sql);
        }
        rst = engineClient.getPortalQuery().ExcuteNoQuery(sql, paramList.toArray(new Parameter[0]));

        logger.info("插入变更合同或解除协议合同数据,执行了 {} 条数据, 合同号为  {}",rst,contractNum);

        int returnInt = engineClient.getPortalQuery().ExcuteNoQuery(updateSql, params);

        logger.info("修改原合同的金额,执行了 {} 条数据, 合同objectID:  {}",returnInt,masterObjectId);

        if (rst == 1 && returnInt == 1) {
            return true;
        }
        return false;
    }

    @Override
    public boolean insertChangesSealData(InstanceData instanceData) throws Exception {
        logger.info("开始写入用印主数据,instaceId ={}", instanceData.getInstanceId());
        int rst;
        String tbName = "i_sealRegistration";

        BizObject bizObject = instanceData.getBizObject();
        String contractNum = (String) bizObject.GetValue("contractNum");
        Parameter[] param = new Parameter[]{new Parameter("contractNumber", DbType.String, contractNum)};
        rst = dataCount(tbName, param);

        if (rst > 0) {
            logger.info("用印数据已存在,无需写入 contractNum ={}", contractNum);
            throw new Exception("用印数据已存在,无需写入");
        }

        List<Parameter> paramList = new ArrayList<>();
        String serviceMarket = (String) bizObject.GetValue("serviceMarket");

        //ObjectID
        paramList.add(new Parameter("ObjectID", DbType.String, UUID.randomUUID()));
        //Name
        paramList.add(new Parameter("Name", DbType.String, bizObject.GetValue("contractName")));
        //CreatedBy
        paramList.add(new Parameter("CreatedBy", DbType.String, bizObject.GetValue("CreatedBy")));
        //CreatedTime
        paramList.add(new Parameter("CreatedTime", DbType.DateTime, bizObject.GetValue("CreatedTime")));
        //合同订立流程id
        paramList.add(new Parameter("instId", DbType.String, instanceData.getInstanceId()));

        //用章编号
        paramList.add(new Parameter("seal", DbType.String, bizObject.GetValue("sealType")));
        //服务市场 [serviceMarket]
        paramList.add(new Parameter("serviceMarket", DbType.String, serviceMarket));
        //合同名称 [contractName]
        paramList.add(new Parameter("contractName", DbType.String, bizObject.GetValue("contractName")));
        //合同编号 [contractNumber]
        paramList.add(new Parameter("contractNumber", DbType.String, contractNum));
        //合同总金额 [totalMoney]
        paramList.add(new Parameter("totalMoney", DbType.String, bizObject.GetValue("totalMoney")));
        paramList.add(new Parameter("oppositeUnit", DbType.String, bizObject.GetValue("oppositeUnit")));
        paramList.add(new Parameter("CRRCAgent", DbType.String, bizObject.GetValue("CRRCAgent")));
        paramList.add(new Parameter("CRRCSignatory", DbType.String, bizObject.GetValue("CRRCSignatory")));
        //盖章日期 [stampedDate]
        paramList.add(new Parameter("stampedDate", DbType.DateTime, bizObject.GetValue("stampedDate")));
        //备注 [remarks]
        paramList.add(new Parameter("remarks", DbType.String, bizObject.GetValue("remarks")));

        String orgUserId =  instanceData.getInstanceContext().getOriginator();
        Unit unit = getEngine().getOrganization().GetParentUnitByCategoryCode(orgUserId,"dept");

        if (unit == null) {
            unit = getEngine().getOrganization().GetUnit(instanceData.getInstanceContext().getOrgUnit());

        }
        paramList.add(new Parameter("createdByDepartment", DbType.String, unit.getName()));
        paramList.add(new Parameter("CreatedByParentId", DbType.String, unit.getObjectID()));
        List<Token> tokens = instanceData.getInstanceContext().getTokens();

        List<Token> collect = tokens.stream().filter(ac -> "Activity50".equals(ac.getActivity())).collect(Collectors.toList());

        //日期 [approvalTime]
        paramList.add(new Parameter("approvalTime", DbType.DateTime, collect.get(0).getCreatedTime()));

        StringBuilder col = new StringBuilder();
        StringBuilder value = new StringBuilder();

        for (Parameter parameter : paramList) {
            col.append(parameter.getName()).append(",");
            value.append("?, ");
        }

        String sql = String.format("insert into %s ( %s) value ( %s ) ", tbName, col.substring(0, col.lastIndexOf(",")),
                value.substring(0, value.lastIndexOf(",")));

        if (logger.isDebugEnabled()) {
            logger.info("用印台账写入主数据 sql = {}", sql);
        }

        rst = engineClient.getPortalQuery().ExcuteNoQuery(sql, paramList.toArray(new Parameter[0]));
        if (rst==1){
            logger.info("用印台账写入主数据成功,合同号： {}", contractNum);
            return true;
        }
        return false;
    }

    @Override
    public boolean updateContractChangesInfo(String masterObjectId){
        String sql = "update i_contractdata set beContractChanges = '有' WHERE ObjectID = ?";
        Parameter[] params = new Parameter[1];
        params[0] = new Parameter("objectId", DbType.String, masterObjectId);
        int i = engineClient.getPortalQuery().ExcuteNoQuery(sql, params);
        if (i == 0) {
            logger.info("修改合同主数据合同变更为变更，执行失败,合同objectId: {}",masterObjectId);
            return false;
        }
        logger.info("修改合同主数据合同变更为变更，执行成功,合同objectId: {}",masterObjectId);
        return true;
    }



    @Override
    public boolean updateContractStatusToNullify(String objectId) {
        String sql = "update i_contractdata set contractStatus = ? WHERE ObjectID = ?";
        Parameter[] params = new Parameter[2];
        params[0] = new Parameter("contractStatus", DbType.String, ContractStatusEnum.htzf.getValue());
        params[1] = new Parameter("objectId", DbType.String, objectId);
        int i = engineClient.getPortalQuery().ExcuteNoQuery(sql, params);
        if (i > 0) {
            logger.info("修改合同主数据合同变更为作废合同，执行成功,合同objectId : {}",objectId);
            return true;
        } else {
            logger.info("修改合同主数据合同变更为作废合同，执行失败,合同objectId : {}",objectId);
            return false;
        }
    }
    @Override
    public boolean updateContractStatusToTermination(String instId) {

        String sql = "update i_contractdata set contractStatus = ? WHERE instId = ?";
        Parameter[] params = new Parameter[2];
        params[0] = new Parameter("contractStatus", DbType.String, ContractStatusEnum.zz_jcht.getValue());
        params[1] = new Parameter("instId", DbType.String, instId);
        int i = engineClient.getPortalQuery().ExcuteNoQuery(sql, params);
        if (i > 0) {
            logger.info("修改合同状态为终结解除合同，执行成功");
            return true;
        } else {
            logger.info("修改合同状态为终结解除合同，执行失败");
            return false;
        }
    }

    @Override
    public boolean updateContractStatusToFulfilled(String contractNum) {
        String sql = "update i_contractdata set contractStatus = ? WHERE contractNum = ?";
        Parameter[] params = new Parameter[2];
        params[0] = new Parameter("contractStatus", DbType.String, ContractStatusEnum.zz_lxwb.getValue());
        params[1] = new Parameter("contractNumber", DbType.String, contractNum);
        int i = engineClient.getPortalQuery().ExcuteNoQuery(sql, params);
        if (i > 0) {
            logger.info("修改合同状态为履行完毕，执行成功");
            return true;
        } else {
            logger.info("修改合同状态为履行完毕，执行失败");
            return false;
        }
    }

    @Override
    public boolean updateOneContractStatusToFulfilled(String instanceId) {
        String sql = "update i_contractdata set contractStatus = ? WHERE instId = ?";
        Parameter[] params = new Parameter[2];
        params[0] = new Parameter("contractStatus", DbType.String, ContractStatusEnum.zz_lxwb.getValue());
        params[1] = new Parameter("instId", DbType.String, instanceId);
        int i = engineClient.getPortalQuery().ExcuteNoQuery(sql, params);
        if (i > 0) {
            logger.info("修改合同状态为履行完毕，执行成功");
            return true;
        } else {
            logger.info("修改合同状态为履行完毕，执行失败");
            return false;
        }
    }

    @Override
    public boolean updateContractStatusToSuspend(String ObjectID) {
        String sql = "update i_contractdata set contractStatus = ? WHERE ObjectID = ?";
        Parameter[] params = new Parameter[2];
        params[0] = new Parameter("contractStatus", DbType.String, ContractStatusEnum.htzzz.getValue());
        params[1] = new Parameter("ObjectID", DbType.String, ObjectID);
        int i = engineClient.getPortalQuery().ExcuteNoQuery(sql, params);
        if (i > 0) {
            logger.info("主合同ObjectID: {}, 修改合同状态为中止中，执行成功",ObjectID);
            return true;
        } else {
            logger.info("主合同ObjectID: {},修改合同状态为中止中，执行失败",ObjectID);
            return false;
        }
    }



    @Override
    public Attachment generateFinalContract(InstanceData instanceData,String attachmentId) throws Exception {

        Attachment attachment ;


        String  isGenerateFinal = (String) instanceData.getBizObject().GetValue("isGenerateFinal");
        // 是否已生成最终文档
        logger.info("(是否已生成最终文档)isGenerateFinal值:   {} ",isGenerateFinal);
        if ( !"是".equals(isGenerateFinal) ){

            attachment  = instanceData.getBizObject().GetAttachment(attachmentId);

            byte[]  byteArr = null;

            boolean flag = false;

            String  beExternal = (String) instanceData.getBizObject().GetValue("beExternal");
            String  replacive = (String) instanceData.getBizObject().GetValue("replacive");
            boolean bool = false;
            if(replacive!=null&&"是".equals(replacive)){
                bool=true;
            }

            String contentType = attachment.getContentType();
            if ("外来合同".equals(beExternal)||bool){
                logger.info("不需要替换占位符逻辑，(外来合同)beExternal值： {}, (需要替换占位符)bool值:  {}",beExternal,bool);
                instanceData.getBizObject().SetValue("isGenerateFinal","是");
                instanceData.Submit();
            }else{
                logger.info("需要替换占位符： {}",replacive);

                if (AttachmentType.doc.equals(contentType) || AttachmentType.docx.equals(contentType)) {
                    Map<String, Object> fieldParam = getFieldParam(instanceData.getBizObject());
                    if (AttachmentType.docx.equals(attachment.getContentType())) {
                        // 锚点变量替换,docx可完全处理，doc会失败
                        DocxUnitl docxUnitl = new DocxUnitl();
                        byteArr = docxUnitl.replaceInDocx(attachment.getContent(),fieldParam);
                    }else if (AttachmentType.doc.equals(contentType)){
                        // 锚点变量替换,doc可完全处理，docx会发生段落格式更改
                        byteArr = Office2Pdf.wordReplace(attachment.getContent(), attachment.getFileName(), fieldParam);
                    }
                    if (byteArr != null) {
                        attachment.setContent(byteArr);
                        attachment.setContentLength(attachment.getContent().length);
                        flag = true;
                    }
                }

            }
            contentType = attachment.getContentType();
            String fileNameAll = attachment.getFileName();

            // 转pdf
            if (AttachmentType.doc.equals(contentType) || AttachmentType.docx.equals(contentType)||fileNameAll.endsWith(".doc")||fileNameAll.endsWith(".docx")) {
                logger.info("开始转pdf");
                byteArr = Office2Pdf.toPdf(attachment.getContent(), Office2Pdf.word);

                if (byteArr != null) {
                    attachment.setContent(byteArr);
                    attachment.setContentType(AttachmentType.pdf);
                    attachment.setContentLength(attachment.getContent().length);
                    String fileName = attachment.getFileName().substring(0, attachment.getFileName().lastIndexOf(".")).concat(".pdf");
                    attachment.setFileName(fileName);
                    attachment.getFileName().substring(0,attachment.getFileName().lastIndexOf(".")).concat(".pdf");
                    flag = true;
                }

            }

            contentType = attachment.getContentType();
            // 添加 水印
            logger.info("文本类型：   {}",contentType);
            if (AttachmentType.pdf.equals(contentType)) {
                // 修改水印格式
                PdfWaterMark.PdfWater zc = PdfWaterMark.grayTextWater("中车戚墅堰机车有限公司", 100, 200, 55, 0.5f, 50);

                String sjImg = Thread.currentThread().getContextClassLoader().getResource("")+"lib/sjyz.png";
                PdfWaterMark.PdfWater sj = PdfWaterMark.getImageWater(sjImg ,-100f,25f,100,0.5f);

                //二维码
                String toUrl = String.format("%s/api/contract/getSignatureWork?instanceId=%s", webHost,instanceData.getInstanceId());
                byte[] maoriByte = MatrixToImageWriter.getMatrixByte(toUrl, "jpg");

                PdfWaterMark.PdfWater tp = PdfWaterMark.getImageWater(maoriByte ,-20f,-20f,50,0.5f);


                List<PdfWaterMark.PdfWater> pdfWaterList =  new ArrayList<>();

                pdfWaterList.add(zc);
                pdfWaterList.add(sj);
                pdfWaterList.add(tp);

                byteArr = PdfWaterMark.addWaterMark(attachment.getContent(), pdfWaterList);

                if (byteArr != null) {
                    attachment.setContent(byteArr);
                    attachment.setContentLength(attachment.getContent().length);
                    flag = true;
                }


            }
            logger.info("flag值:   {}",flag);
            if (flag) {

                List<AttachmentHeader> list = instanceData.getBizObject().GetAttachmentHeaders("contractFileFinal", BoolMatchValue.True, null);

                if (list.size()>0){
                    attachment.setObjectID(list.get(0).getObjectID());
                }else{
                    attachment.setObjectID(UUID.randomUUID().toString());
                }

                attachment.setObjectID(UUID.randomUUID().toString());
                attachment.setCreatedTime(new Date());
                attachment.setModifiedTime(attachment.getCreatedTime());
                attachment.setDataField("contractFileFinal");

                String s = engineClient.getBizObjectManager().AddAttachment(attachment);

                logger.info("添加转换PDF附件成功，pdf附件ID： {}",s);
                instanceData.getBizObject().SetValue("isGenerateFinal","是");

                instanceData.Submit();

                logger.info("已执行更新");
            }

        }else{

            List<AttachmentHeader> list = instanceData.getBizObject().GetAttachmentHeaders("contractFileFinal", BoolMatchValue.True, null);
            if (list.size()>0){
                attachment =  instanceData.getBizObject().GetAttachment(list.get(0).getAttachmentID());
            }else{
                instanceData.getBizObject().SetValue("isGenerateFinal","否");
                logger.info("转换pdf附件失败");
                return  null;
            }

        }

        return attachment;
    }



    /**
     *
     * @param biz   表单数据
     * @param attachment 合同文件数据字段 ("contractFile")
     * @return
     */
    @Override
    public Attachment fieldReplace(BizObject biz,Attachment attachment) throws Exception {

        if (AttachmentType.docx.equals(attachment.getContentType())) {
            // 锚点变量替换,docx可完全处理，doc会失败
            DocxUnitl docxUnitl = new DocxUnitl();
            byte[] bytes = docxUnitl.replaceInDocx(attachment.getContent(), getFieldParam(biz));
            attachment.setContent(bytes);
        }else if(AttachmentType.doc.equals(attachment.getContentType())){
            // 锚点变量替换,doc可完全处理，docx会发生段落格式更改
            byte[] bytes = Office2Pdf.wordReplace(attachment.getContent(), attachment.getFileName(), getFieldParam(biz));
            attachment.setContent(bytes);
        }
        return attachment;
    }
    private  static  final String[]  fieldParamArr = ("signDate,signAddr,firstPartyName,signatory,businesRegistNumber," +
            "contractName,contractNum,totalMoney,secondPartyName,secondSignatory," +
            "secondBusinesRegistNumber,secondFaxNumber,secondMailingAddress,secondPostCode,secondMail,secondbank," +
            "secondBankAccount,secondTaxNumber,firstFaxNumber,firstMailingAddress,firstPostCode,firstMail," +
            "firstbank,firstBankAccount,firstTaxNumber,secondContractsMobile,firstContractsMobile,firstLegalPerson,secondLegalPerson").split(",");

    private Map<String, Object> getFieldParam(BizObject biz) throws Exception {
        Map<String, Object> map = new HashMap<String, Object>();
        //获取参数
        Object temp;
        for (int i = 0; i < fieldParamArr.length; i++) {
            temp = biz.GetValue(fieldParamArr[i]);
            if (temp != null) {

                map.put(fieldParamArr[i], QjcUtils.contractParamFilter(temp));
            }
        }
        return map;
    }


    @Override
    public Map<String, Object> getContractByInstanceId(String instanceId, String code)throws Exception {
        HashMap<String, Object> stringObjectHashMap = new HashMap<>();
        InstanceData instanceData = new InstanceData(getEngine(), instanceId, code);
        BizObject bizObject = instanceData.getBizObject();
        stringObjectHashMap.put("beExternal", bizObject.GetValue("beExternal"));
        stringObjectHashMap.put("firstPartyName", bizObject.GetValue("firstPartyName"));
        stringObjectHashMap.put("firstBusinesRegistNumber", bizObject.GetValue("businesRegistNumber"));
        stringObjectHashMap.put("firstAgent", bizObject.GetValue("firstAgent"));
        stringObjectHashMap.put("firstSignatory", bizObject.GetValue("signatory"));
        stringObjectHashMap.put("firstLegalPerson", bizObject.GetValue("firstLegalPerson"));
        stringObjectHashMap.put("firstContractsMobile", bizObject.GetValue("firstContractsMobile"));
        stringObjectHashMap.put("firstFaxNumber", bizObject.GetValue("firstFaxNumber"));
        stringObjectHashMap.put("firstMailingAddress", bizObject.GetValue("firstMailingAddress"));
        stringObjectHashMap.put("firstPostCode", bizObject.GetValue("firstPostCode"));
        stringObjectHashMap.put("firstMail", bizObject.GetValue("firstMail"));
        stringObjectHashMap.put("firstBank", bizObject.GetValue("firstbank"));
        stringObjectHashMap.put("firstBankAccount", bizObject.GetValue("firstBankAccount"));
        stringObjectHashMap.put("firstTaxNumber", bizObject.GetValue("firstTaxNumber"));
        stringObjectHashMap.put("firstCreditLine", bizObject.GetValue("firstCreditLine"));

        stringObjectHashMap.put("secondPartyName", bizObject.GetValue("secondPartyName"));
        stringObjectHashMap.put("secondBusinesRegistNumber", bizObject.GetValue("secondBusinesRegistNumber"));
        stringObjectHashMap.put("secondSignatory", bizObject.GetValue("secondSignatory"));
        stringObjectHashMap.put("secondAgent", bizObject.GetValue("secondAgent"));
        stringObjectHashMap.put("secondLegalPerson", bizObject.GetValue("secondLegalPerson"));
        stringObjectHashMap.put("secondContractsMobile", bizObject.GetValue("secondContractsMobile"));
        stringObjectHashMap.put("secondFaxNumber", bizObject.GetValue("secondFaxNumber"));
        stringObjectHashMap.put("secondMailingAddress", bizObject.GetValue("secondMailingAddress"));
        stringObjectHashMap.put("secondPostCode", bizObject.GetValue("secondPostCode"));
        stringObjectHashMap.put("secondMail", bizObject.GetValue("secondMail"));
        stringObjectHashMap.put("secondBank", bizObject.GetValue("secondbank"));
        stringObjectHashMap.put("secondBankAccount", bizObject.GetValue("secondBankAccount"));
        stringObjectHashMap.put("secondTaxNumber", bizObject.GetValue("secondTaxNumber"));
        stringObjectHashMap.put("secondCreditLine", bizObject.GetValue("secondCreditLine"));

        stringObjectHashMap.put("creditRating", bizObject.GetValue("creditRating"));
        stringObjectHashMap.put("deadlineForPerformance", bizObject.GetValue("deadlineForPerformance"));
        stringObjectHashMap.put("deputyLeader", bizObject.GetValue("deputyLeader"));
        stringObjectHashMap.put("principalLeader", bizObject.GetValue("principalLeader"));
        stringObjectHashMap.put("chargeLeader", bizObject.GetValue("chargeLeader"));
        stringObjectHashMap.put("countersignedStaff", bizObject.GetValue("countersignedStaff"));
        stringObjectHashMap.put("expensesOrReceipts", bizObject.GetValue("expensesOrReceipts"));
        stringObjectHashMap.put("sealType", bizObject.GetValue("sealType"));
        stringObjectHashMap.put("serviceMarket", bizObject.GetValue("serviceMarket"));
        return stringObjectHashMap;

    }

    @Override
    public void contractStatusUpdate(String instanceId,String status) throws Exception {
        String sql = "select objectId,contractStatus from i_contractdata where instId=?";

        Parameter instId = new Parameter("instId", DbType.String, instanceId);
        DataTable dataTable = engineClient.getQuery().QueryTable(sql, new Parameter[]{instId}, false);

        String updateSql = "update i_contractdata set contractStatus =? where objectId = ?";

        if (dataTable != null && dataTable.getRows().size()>0){
            String objectId = dataTable.getRows().get(0).getString("objectId");
            String contractStatus = dataTable.getRows().get(0).getString("contractStatus");

            Parameter[] parameters = new Parameter[2];

            boolean b = contractStatusEdit(status, contractStatus);

            if (b) {

                parameters[0] = new Parameter("contractStatus", DbType.String, status);
                parameters[1] = new Parameter("objectId", DbType.String, objectId);

                int i = engineClient.getPortalQuery().ExcuteNoQuery(updateSql, parameters);

                if (i > 0) {
                    logger.info("合同状态修改成功,当前状态={},变更结果状态={}",contractStatus,status);

                }else {
                    logger.info("合同状态修改失败,数据不存在,当前状态={},变更结果状态={}",contractStatus,status);
                }

            }else{
                logger.info("合同状态修改失败,当前状态={},变更结果状态={}",contractStatus,status);
                throw  new Exception("合同状态修改失败");
            }
        }
    }


    private boolean contractStatusEdit(String status, String contractStatus)   {
        boolean f = false;
        //合同签署中 改为 合同执行中
        if (ContractStatusEnum.htqsz.getValue().equals(contractStatus) && ContractStatusEnum.zxz.getValue().equals(status) ){

            f = true;
        }else if(ContractStatusEnum.htqsz.getValue().equals(contractStatus) &&  ContractStatusEnum.htzf.getValue().equals(status)){
            f = true;
        }

        return f;
    }
    @Override
    public Object getContractFile(String originalContractNum,String userId,String bizObjectId,String bizObjectSchemaCode,String dataField) throws Exception {
        ResponseResult rst = new ResponseResult(-1L,"",null);
        String sql ="select instId from i_contractdata where originalContractNum = ?";
        Parameter contractNum = new Parameter("originalContractNum", DbType.String, originalContractNum);
        DataTable dataTable = engineClient.getQuery().QueryTable(sql, new Parameter[]{contractNum}, false);

        if (dataTable != null && dataTable.getRows().size()>0){
            List<Object> objects = new ArrayList<>();
            for (int i = 0; i < dataTable.getRows().size(); i++) {
                String instId = dataTable.getRows().get(i).getString("instId");
                System.out.println("instId :   "+instId);
                InstanceData instanceData = new InstanceData(getEngine(), instId,User.AdministratorID);
                List<AttachmentHeader> list0 = instanceData.getBizObject().GetAttachmentHeaders("contractFileFinal", BoolMatchValue.True, null);
                List<AttachmentHeader> list1 = instanceData.getBizObject().GetAttachmentHeaders("contractAttachment", BoolMatchValue.True, null);
//                List<AttachmentHeader> list2 = instanceData.getBizObject().GetAttachmentHeaders("changeAgreement", BoolMatchValue.True, null);
                System.out.println("o1 :   "+list0);
                System.out.println("o2 :   "+list1);
//                System.out.println("o3 :   "+list2);
                if (list0 != null && list0.size() > 0) {
                    for (int j = 0; j <list0.size() ; j++) {
                        Map<String, Object> map = getFile(instanceData, list0.get(j), userId, bizObjectId, bizObjectSchemaCode, dataField);
                        objects.add(map);
                    }
                }
                if (list1 != null && list1.size() > 0) {
                    for (int j = 0; j <list1.size() ; j++) {
                        Map<String, Object> map = getFile(instanceData, list1.get(j), userId, bizObjectId, bizObjectSchemaCode, dataField);
                        objects.add(map);
                    }
                }
//                if (list2 != null && list2.size() > 0) {
//                    for (int j = 0; j <list2.size() ; j++) {
//                        Map<String, Object> map = getFile(instanceData, list2.get(j), userId, bizObjectId, bizObjectSchemaCode, dataField);
//                        objects.add(map);
//                    }
//                }

            }
            List newList = objects.stream().distinct().collect(Collectors.toList());
            System.out.println("o总 :   "+newList);
            logger.info("o总的有 {} 个元素",newList.size());
            rst.setErrcode(0L);
            rst.setErrmsg("成功");
            rst.setData(newList);
        }
        return rst;
    }

    @Override
    public boolean updatePerform(String contractNum,String timeOfPerformance,String totalActualPayment) {
        String sql ="select totalMoney,endDate from i_contractdata where contractNum = ?";
        Parameter[] params = new Parameter[1];
        params[0] = new Parameter("contractNum", DbType.String, contractNum);
        DataTable dataTable = getEngine().getQuery().QueryTable(sql,params,false);
        DataRowCollection rows = dataTable.getRows();
        String Overdue="否";
        if (rows != null && rows.size() > 0) {
            DataRow dataRow = rows.get(0);
            try {
                String endDate = dataRow.getString("endDate");
                boolean b = timeCompare(endDate, timeOfPerformance);
                //超期
                if (b){
                    Overdue="是";
                }
                String updateSql = "update i_contractdata set actualPayment = ?,performanceTime=?, Overdue =?WHERE contractNum = ?";
                Parameter[] params2 = new Parameter[4];
                params2[0] = new Parameter("actualPayment", DbType.String, totalActualPayment);
                params2[1] = new Parameter("performanceTime", DbType.DateTime, timeOfPerformance);
                params2[2] = new Parameter("Overdue", DbType.String, Overdue);
                params2[3] = new Parameter("contractNum", DbType.String, contractNum);
                int i = getEngine().getPortalQuery().ExcuteNoQuery(updateSql, params2);
                if (i != 1) {
                    logger.info("更新主数据 合同总金额和最晚的履行时间，执行失败");
                    return false;
                }else {
                    logger.info("更新主数据 合同总金额和最晚的履行时间，执行成功");
                    return true;
                }
            } catch (DataException e) {
                logger.info("更新主数据 合同总金额和最晚的履行时间，执行失败");
                e.printStackTrace();
                return false;
            }
        }else {
            logger.info("更新主数据 合同总金额和最晚的履行时间，执行失败");
        }

        return false;
    }

    private Map<String, Object> getFile (InstanceData instanceData,AttachmentHeader header ,String userId,String bizObjectId,String bizObjectSchemaCode,String dataField)throws  Exception{

        Date date  = new Date();
        header.getAttachmentID();

        header.getDownloadUrl();

        Attachment attc = instanceData.getBizObject().GetAttachment(header.getAttachmentID());


        Attachment attachment = new Attachment();
        attachment.setObjectID(UUID.randomUUID().toString());
        attachment.setContent(attc.getContent());
        attachment.setContentType(attc.getContentType());
        attachment.setCreatedBy(userId);
        attachment.setCreatedTime(date);
        attachment.setFileName(attc.getFileName());
        attachment.setLastVersion(true);
        attachment.setModifiedTime(date);
        attachment.setBizObjectSchemaCode(bizObjectSchemaCode);
        attachment.setContentLength(attc.getContentLength());
        attachment.setBizObjectId(bizObjectId);
        attachment.setDataField(dataField);


        String result = getEngine().getBizObjectManager().AddAttachment(attachment);

        Map<String, Object> map = new HashMap<>(6);
        map.put("Code",result);
        map.put("ContentType",attachment.getContentType());
        map.put("Name",attachment.getFileName());
        map.put("Size",attachment.getContentLength());
        map.put("Url",attachment.getDownloadUrl());
        String url = String.format("/Portal/ReadAttachment/Read?BizObjectSchemaCode=%s&BizObjectID=%s&AttachmentID=%s&OpenMethod=0",
                bizObjectSchemaCode,bizObjectId,result);
        map.put("Url",url);
        return map;
    }



}



